"""
Core DeepSeek client functionality
"""

import os
import logging
import requests
import time
from dataclasses import dataclass
from typing import Optional, Dict, Any, List
from pathlib import Path

from .history import QAHistoryManager

# Auto-load .env file if present
def _auto_load_env():
    """Automatically load .env file from package directory or current directory"""
    try:
        from .utils import load_env_file

        return load_env_file()
    except ImportError:
        return False

# Auto-load environment on import if enabled
if os.getenv('QWEN_AUTO_LOAD_ENV', 'true').lower() == 'true':
    _auto_load_env()


@dataclass
class DeepSeekConfig:
    """Configuration for DeepSeek client"""
    api_key: str
    base_url: str = "https://api.deepseek.com"
    model_name: str = "deepseek-chat"
    max_tokens: int = 4096
    temperature: float = 0.3
    top_p: float = 0.9
    timeout: int = 120
    skip_validation: bool = False
    
    @classmethod
    def from_env(cls, require_api_key: bool = None) -> 'DeepSeekConfig':
        """Create config from environment variables
        
        Args:
            require_api_key: Whether to require API key validation. 
                           If None, uses QWEN_SKIP_API_VALIDATION env var.
        """
        # Check if we should skip API key validation
        if require_api_key is None:
            skip_validation = os.getenv('QWEN_SKIP_API_VALIDATION', 'false').lower() == 'true'
        else:
            skip_validation = not require_api_key
        
        api_key = os.getenv('DEEPSEEK_API_KEY', '')
        
        # Only require API key if validation is not skipped
        if not skip_validation and not api_key:
            raise ValueError("DEEPSEEK_API_KEY environment variable is required")
        
        return cls(
            api_key=api_key,
            base_url=os.getenv('DEEPSEEK_BASE_URL', cls.base_url),
            model_name=os.getenv('DEEPSEEK_MODEL', cls.model_name),
            max_tokens=int(os.getenv('QWEN_MAX_TOKENS', str(cls.max_tokens))),
            temperature=float(os.getenv('QWEN_TEMPERATURE', str(cls.temperature))),
            top_p=float(os.getenv('QWEN_TOP_P', str(cls.top_p))),
            timeout=int(os.getenv('QWEN_TIMEOUT', str(cls.timeout))),
            skip_validation=skip_validation
        )
    
    @classmethod 
    def auto_config(cls) -> 'DeepSeekConfig':
        """Auto-create config with .env support and smart validation"""
        # Auto-load env if not already done
        _auto_load_env()
        
        # Create config with validation based on .env settings
        return cls.from_env()


class DeepSeekClient:
    """Standalone DeepSeek model client"""
    
    def __init__(self, config: DeepSeekConfig, logger: Optional[logging.Logger] = None,
                 enable_history: bool = True):
        self.config = config
        self.logger = logger or logging.getLogger(__name__)
        self.session = requests.Session()
        
        # Initialize history manager if enabled
        self.history_manager = QAHistoryManager() if enable_history else None
        
        # Only set up authentication if we have an API key
        if config.api_key:
            self.session.headers.update({
                'Authorization': f'Bearer {config.api_key}',
                'Content-Type': 'application/json'
            })
        
        validation_status = "skipped" if config.skip_validation else "enabled"
        history_status = "enabled" if enable_history else "disabled"
        self.logger.info(f"DeepSeekClient initialized with model: {config.model_name} (validation: {validation_status}, history: {history_status})")
    
    @classmethod
    def auto_create(cls, logger: Optional[logging.Logger] = None) -> 'DeepSeekClient':
        """Auto-create client with .env configuration"""
        config = DeepSeekConfig.auto_config()
        return cls(config, logger)
    
    def ask(self, question: str, system_prompt: Optional[str] = None, **kwargs) -> str:
        """
        Ask DeepSeek model a question
        
        Args:
            question: The question to ask
            system_prompt: Optional system prompt to set context
            **kwargs: Additional parameters (max_tokens, temperature, etc.)
        
        Returns:
            String response from the model
        """
        start_time = time.time()
        
        messages = []
        
        if system_prompt:
            messages.append({"role": "system", "content": system_prompt})
        
        messages.append({"role": "user", "content": question})
        
        payload = {
            "model": self.config.model_name,
            "messages": messages,
            "max_tokens": kwargs.get('max_tokens', self.config.max_tokens),
            "temperature": kwargs.get('temperature', self.config.temperature),
            "top_p": kwargs.get('top_p', self.config.top_p)
        }
        
        # Check if we can make API calls
        if not self.config.api_key and not self.config.skip_validation:
            raise ValueError("No API key provided and validation not skipped")
        
        try:
            # If no API key but validation is skipped, return mock response
            if not self.config.api_key and self.config.skip_validation:
                mock_response = f"[Mock response for: {question[:50]}...] This is a simulated response when API key validation is skipped."
                self.logger.info(f"Returning mock response (no API key, validation skipped)")
                
                # Record mock response in history
                if self.history_manager:
                    response_time = time.time() - start_time
                    self.history_manager.add_entry(
                        question=question,
                        answer=mock_response,
                        model="deepseek",
                        system_prompt=system_prompt,
                        response_time=response_time,
                        **kwargs
                    )
                
                return mock_response
            
            response = self.session.post(
                f"{self.config.base_url}/chat/completions",
                json=payload,
                timeout=kwargs.get('timeout', self.config.timeout)
            )
            
            if response.status_code == 200:
                result = response.json()
                if 'choices' in result and len(result['choices']) > 0:
                    answer = result['choices'][0]['message']['content'].strip()
                    response_time = time.time() - start_time
                    self.logger.info(f"DeepSeek responded with {len(answer)} characters")
                    
                    # Record successful response in history
                    if self.history_manager:
                        # Extract token usage if available
                        tokens_used = result.get('usage', {}).get('total_tokens')
                        self.history_manager.add_entry(
                            question=question,
                            answer=answer,
                            model="deepseek",
                            system_prompt=system_prompt,
                            response_time=response_time,
                            tokens_used=tokens_used,
                            **kwargs
                        )
                    
                    return answer
                else:
                    self.logger.warning("No choices in DeepSeek response")
                    return ""
            else:
                error_msg = f"DeepSeek API error {response.status_code}: {response.text}"
                self.logger.error(error_msg)
                raise Exception(error_msg)
                
        except Exception as e:
            self.logger.error(f"Failed to call DeepSeek: {e}")
            raise
    
    def ask_with_context(self, question: str, context: Dict[str, str], 
                        system_prompt: Optional[str] = None, **kwargs) -> str:
        """
        Ask DeepSeek with relevant context information
        
        Args:
            question: The question to ask
            context: Dictionary of context information {title: content}
            system_prompt: Optional system prompt
            **kwargs: Additional parameters
        
        Returns:
            String response from the model
        """
        context_section = self._format_context(context)
        
        full_question = f"{question}\n\n{context_section}" if context_section else question
        
        return self.ask(full_question, system_prompt, **kwargs)
    
    def ask_chinese_technical(self, question: str, context: Optional[Dict[str, str]] = None, 
                             domain: str = "技术", **kwargs) -> str:
        """
        Ask DeepSeek for Chinese technical response
        
        Args:
            question: Technical question in Chinese or English
            context: Optional context information
            domain: Technical domain (e.g., "数据同化", "机器学习")
            **kwargs: Additional parameters
        
        Returns:
            Chinese technical response
        """
        system_prompt = f"""你是{domain}领域的专家。请用中文回答技术问题，提供：
1. 详细的技术解释
2. 具体的实现方法
3. 相关的代码示例（如适用）
4. 实际的配置参数和操作步骤
5. 潜在的风险点和解决方案

请提供专业、准确、实用的技术指导。"""

        # Pass chinese_mode and domain parameters for history recording
        kwargs['chinese_mode'] = True
        kwargs['domain'] = domain
        kwargs['context'] = context
        
        if context:
            return self.ask_with_context(question, context, system_prompt, **kwargs)
        else:
            return self.ask(question, system_prompt, **kwargs)
    
    def batch_ask(self, questions: List[str], system_prompt: Optional[str] = None, 
                  **kwargs) -> Dict[str, str]:
        """
        Ask multiple questions in batch
        
        Args:
            questions: List of questions
            system_prompt: Optional system prompt
            **kwargs: Additional parameters
        
        Returns:
            Dictionary mapping questions to responses
        """
        results = {}
        
        for i, question in enumerate(questions, 1):
            self.logger.info(f"Processing question {i}/{len(questions)}: {question[:50]}...")
            try:
                answer = self.ask(question, system_prompt, **kwargs)
                results[question] = answer
            except Exception as e:
                self.logger.error(f"Failed to process question {i}: {e}")
                results[question] = f"[Error: {str(e)}]"
        
        return results
    
    def _format_context(self, context: Dict[str, str]) -> str:
        """Format context information for inclusion in prompt"""
        if not context:
            return ""
        
        context_lines = [
            "## 相关背景信息",
            "",
            "以下是相关的背景信息，可作为参考：",
            ""
        ]
        
        for i, (title, content) in enumerate(context.items(), 1):
            context_lines.extend([
                f"### 背景{i}: {title}",
                "",
                content[:1000] + ("..." if len(content) > 1000 else ""),
                "",
                "---",
                ""
            ])
        
        context_lines.extend([
            "请基于上述背景信息和当前问题进行分析和回答。",
            ""
        ])
        
        return "\n".join(context_lines)
    
    def validate_connection(self) -> bool:
        """
        Validate connection to DeepSeek API
        
        Returns:
            True if connection is successful, False otherwise
        """
        # If validation is skipped, return True without testing
        if self.config.skip_validation:
            self.logger.info("Connection validation skipped (QWEN_SKIP_API_VALIDATION=true)")
            return True
        
        # If no API key, can't validate
        if not self.config.api_key:
            self.logger.warning("No API key provided, cannot validate connection")
            return False
            
        try:
            test_response = self.ask("Hello", max_tokens=10)
            return len(test_response.strip()) > 0
        except Exception as e:
            self.logger.error(f"Connection validation failed: {e}")
            return False
